home *** CD-ROM | disk | FTP | other *** search
/ Into That Dark Night / Into That Dark Night.iso / pc / YadVashem / Database / WorkDir / ICONLEX.pl < prev    next >
Encoding:
Text File  |  1999-07-13  |  17.5 KB  |  462 lines

  1. # Parsing The lexicon files of and finding keywords etc.
  2. # Written: Eli Zvuluny - 
  3. #  Possible Worlds
  4. #
  5. # Version Hisotry
  6. #  18/10/98 - Version changed after having the file with HTML tags 
  7. #   1/11/98 - Add extraction of   (should be taken on HTML2DOC, but in order to not run
  8. #             everything twice  - 
  9. #  29/11/98 - Change the separation character to | instead of , due to change in access 
  10. #  11/7/99 - Insert the last Tink changes.
  11. #  
  12. # iconLexParse.pl search a list of text files, for an occurance of 
  13. # lexicon values.
  14. #
  15. # The lex values is taken from the file lexItems.txt generated by access.
  16.  
  17. #  require 'StandardFile.pl';
  18.  
  19. # First start to process all files in the current folder for an existance of
  20. # keywords (i.e. for a lexicon entries)
  21.  
  22.    use Cwd;
  23.    use English;
  24.    
  25.    
  26.    $keyFile = "lexItems.txt";    # file name generated by access, in the directory "workDir"
  27.    open (ERRFILE, ">keyErr.lex");
  28.    print "==== Processing the keywords (lexItems.txt) file =====\n";
  29.    open (KEYFILE, "<$keyFile") or die "can't open file $keyFile\n";
  30.  LOOPKEY:   while (<KEYFILE>) {
  31.       $current_line = $_;
  32.       chomp;
  33.       ($tmpNum, $tmpKey) = $current_line =~ /^(\d+)\|(.+)$/;
  34.       $tmpKey =~ tr/a-z/A-Z/;
  35.       # in case of multi words, extract extra blanks
  36.       @tmpArr = split(/\s+/,$tmpKey);
  37.       $tmpKey = join(" ",@tmpArr);
  38. #      print "Before Keys $tmpKey\n";
  39.       ($tmpKey, $parenKey) = $tmpKey =~ /^([^\(\)]+[^\s])\s*(\([^\(\)].*\))*\s*$/;
  40. #      print "Keys $tmpKey, $parenKey\n";
  41.       chop($tmpKey) if $tmpKey =~ /[\,\.\:\;\!\?\"\x93\x94\x92\x91\x27]$/;  # extract possible extra characters
  42.       next LOOPKEY if  ($tmpKey =~ /^\s*$/);   # Ignore blank lex items
  43.       if ($lexItems{$tmpKey}) {
  44.          print "*** The lexicon item: [$tmpKey] already exists\n";
  45.          print ERRFILE "*** The lexicon item: [$tmpKey] already exists\n";
  46.  
  47.       } else {
  48.         $lexItems{$tmpKey} = $tmpNum;
  49.         $lexNums{$tmpNum} = $tmpKey;  # and the inverted list
  50.       }
  51.       if ($parenKey) {
  52.          $parenKey =~ s/\((.*)\)/\1/;
  53.          chop($parenKey) if $parenKey =~ /[\,\.\:]$/;  # extract possible extra characters
  54.          if ($lexItems{$parenKey}) {
  55.             print "*** The lexicon item: [$parenKey] already exists\n";
  56.             print ERRFILE "*** The lexicon item: [$parenKey] already exists\n";
  57.  
  58.          } else {
  59.            $lexItems{$parenKey} = $tmpNum;
  60.            $lexNums{$tmpNum} = $tmpKey;  # and the inverted list
  61.          }
  62.       }
  63.    } # while KEYFILE
  64.    close (KEYFILE);
  65.    foreach  $key (sort (keys (%lexItems))) {
  66.      print "$key $lexItems{$key}\n";
  67.     # check if there is a paired keywords separated with a ","
  68.      if ($key =~ /^([^\,]+)\s*\,\s*([^\,\(\)]+)(\s*\(.*\))*$/) {
  69. #       print "paired - $1 - $2 $key, $lexItems{$key}\n";
  70.         $pairedItems{$1} = $2;
  71.         $pairedItems{$2} = $1;
  72.         $pairLexKey{$1 . " " . $2} = $lexItems{$key};
  73.         $pairLexKey{$2 . " " . $1} = $lexItems{$key};
  74. #       print "paired - $1 - $2 $key, $lexItems{$key}\n";
  75.         if (!$lexItems{$1}) { # the If enforce the existance of a normal entry which = first part of pair
  76.            $lexItems{$1} = $lexItems{$key};  # this will be the last choice for a pair element.
  77. #           $lexNums{$idx-1} = $1;
  78.         }
  79.         $firstPaired{$lexItems{$key}} = $1;  # used for a case of multipled paired entries (such as
  80.         # (Kaplan, Moshe - Kaplan, Shimon), in those cases, on the second entry (Shimon), when
  81.         # there is a simple reference to Kaplan (a lot), the system mark it by mistake since
  82.         # it assumes that it refers to the first Kaplan, and not to the titled keyword.
  83.      }
  84.      else { #if it is a multiword, save the first word, and max number of words for that item. 
  85.          @tmpArr = split(/\s+/,$key);
  86.          if ($#tmpArr > 1) {
  87.             $tmpVal =  $firstWord{$tmpArr[0]};
  88.             if ($#tmpArr > $tmpVal) {
  89.                $firstWord{$tmpArr[0]} = $#tmpArr+1;
  90.             }
  91. #            print " Multiword $Key, $tmpArr[0], $firstWord{$tmpArr[0]}\n";
  92.          } 
  93.      } #if - elsif
  94.      if (($beforeParen, $inParen) = $key =~ /^\s*([^\s]+)\s*\((.+)\s*\)$/) {
  95.          chop($beforeParen) if $beforeParen =~ /[\,\.\:\;\!\?\"\x93\x94\x92\x91\x27]$/;  # extract possible extra characters
  96.          chop($inParen) if $inParen =~ /[\,\.\:\;\!\?\"\x93\x94\x92\x91\x27]$/;  # extract possible extra characters
  97.         if (!$lexItems{$inParen}) {
  98.            $lexItems{$inParen} = $lexItems{$key};
  99.         }
  100.         if (!$lexItems{$beforeParen}) {
  101.            $lexItems{$beforeParen} = $lexItems{$key};
  102.         }
  103.      }  # there is another keyword in Parentheses
  104.    } #foreach
  105.    $dirname = "lexFiles";
  106.    $currentDir = cwd;
  107. #   print "$currentDir \n";
  108. #   printKeyArr (\%pairLexKey);
  109.    # now get the base dir, which is the parent directory, and the directory separator
  110.    ($dirSep,$lastDir) = $currentDir =~ /([\\\:])([^\\\:]+)$/;
  111. #   $baseDir =  $`;
  112.    $baseDir =  $PREMATCH;
  113.    @dirVec = ("ItmText", "Lexicon", "Orgtext", "TstmWrt");
  114.    foreach $theDir (@dirVec) {  
  115.       $dirname = "$baseDir$dirSep" . "Text" . "$dirSep$theDir";
  116.       mkdir ("${dirname}1", umask());
  117.        opendir(CURDIR, $dirname)  or die "can't open $dirname\n";
  118.           chdir($dirname);
  119.  
  120.        $lastKey = "";
  121.     
  122.        print "==== Start processing the lexicon files in $theDir =====\n";
  123.        while ($curFile = readdir(CURDIR)) {
  124.           if ($curFile =~ /txt\d+\.doc/i) {
  125.             print "-----$curFile----\n";
  126.             $veryBigLine = "";
  127.             open (FILEIN, "<$curFile") or die "can't open file\n";
  128.              open (TXTFILE, ">${dirname}1$dirSep$curFile");
  129.             while  (<FILEIN>) {
  130.               $current_line = $_;
  131.                  $veryBigLine = $veryBigLine . $_;
  132.             } # while
  133.             # extract key number from file name
  134.             ($fileIdx) = $curFile =~ /txt(\d+)\.doc/i;
  135.             # set the value of lastKey, which is the key associated with the file.
  136.             $lastKey = $lexNums{$fileIdx};
  137. #            print "Last key is $lastKey\n";
  138.             if (!$lastKey) {
  139.                $lastKey = "stamstamstam";
  140.             }
  141.              &closeKeyItem($lastKey);  # handle last keyword
  142.             
  143.             close (FILEIN);
  144.           } #if
  145.        } # while
  146.    } # foreach @dirVec
  147.    close (KEYFILE);
  148.    close (ERRFILE);
  149.    print "==== Successful processing =====\n";
  150.    
  151.  
  152. sub closeKeyItem
  153. {
  154.     local($curKey) = @_;
  155.     if ($curKey eq "") {
  156. #       print "Nothing to do now (really) !!!!!\n";
  157.     } else {
  158.     $veryBigLine =~ s/\n/ # /g;
  159.     # try to see if there are exactly the same with bold and Italic
  160. #    $veryBigLine =~ s/^(\s*)(\<B\>)([^\<])\s*\#*(\<\/B\>)\s*\<I\>\3\>\#+\/I\>/$1$2$3$4/i;
  161.     # now replace all the Bold and Italic with @b and @i.
  162.       while (($HtmlTag,$innerString) = $veryBigLine =~ /<([IB])>([^[<>]*)<\/\1>/i) {
  163.          # found, replace all the internal words with @i@ or @b@
  164.          $beforeStr = $PREMATCH;
  165.          $afterStr = $POSTMATCH;
  166.          @markedWords = split(/\s+/,$innerString);
  167. #         print " $HtmlTag,$innerString Number is $#markedWords\n";
  168.          if ($#markedWords >= 0) {
  169.             for ($i = 0; $i <= $#markedWords; $i++) {
  170.                if ($markedWords [$i] !~ /^\s*$/) {
  171. #                  print "$markedWords[$i]\n";
  172.                   if ($markedWords [$i] ne "#") {
  173.                      $markedWords [$i] = '@' . $HtmlTag . '@' . $markedWords [$i];
  174.                   } 
  175.                }
  176.             } # for
  177.          } # if there is something between tag and its closure
  178.          $veryBigLine = $beforeStr . " " . join(" ",@markedWords) . " " . $afterStr;
  179.       } # while
  180.       &handleLines($lastKey, $veryBigLine);
  181.       
  182.       $veryBigLine = join (" ",@splitWords);
  183.       $veryBigLine =~ s/\s*\007\s*/\007/g;
  184.       $veryBigLine =~ s/\007/\n/g;
  185.       #
  186.       # extract empty lines  till first relevant line
  187.       #
  188.       $veryBigLine =~ s/^\s*(\#\s)*(\s\#)*//i;
  189.       # now check for cases of many new lines
  190.       $veryBigLine =~ s/(\#\s+){4,}/\# /g;
  191.       print TXTFILE $veryBigLine;
  192.       $veryBigLine = "";
  193.       close (TXTFILE);
  194.     }
  195. } # closeKeyItem
  196.  
  197. sub handleLines
  198. {
  199.     local($curKey, $theLine) = @_;
  200.     my $i, $tmpWord;
  201.     
  202.     $theLine =~ s/\ \;/   /ig;   # Horizontal Tab 
  203.     $theLine =~ s/\−\;/   /ig;   # ????? 
  204.     # first replace the new line with another symbol
  205.     $theLine =~ s/\n/\007/g;
  206.     @splitWords = split(/\s+/,$theLine);
  207.     # The algorithm for finding if a keyword already exist:
  208.     # First of all naturally translate all words into uppercase characters.
  209.     # The priorities for a keyword is:
  210.     # 1. Key word that contains couple of words.
  211.     # 2. Key words that compose of 2 parts weparated by ",". <part1>,<part2>
  212.     #    The possible combinations are: <part1> <part2> | <part2> <part1> | <part1>
  213.     # 3. Single word that did not fulfill any of the previous criterias
  214.     #
  215.     # on All cases, we may try to use the canonic version of the word.
  216.     # in all cases we do not look for the current file keyword.
  217.     $prevWords = "";
  218.     $numOfWords = 0;
  219. #    print "split words $#splitWords\n";
  220.     for ($i = 0; $i <= $#splitWords; $i++) { 
  221.        $tmpWord = $splitWords[$i];
  222.        $tmpWord =~ tr/a-z/A-Z/;
  223.        $tmpWord =~ s/^\@[IB]\@(.*)$/\1/i;
  224. #       if ($tmpWord =~ /^<[\/]?b>/i) {
  225. #          print "$tmpWord\n";
  226. #       }
  227. #       $tmpWord =~ s/^<[\/]?b>(.+)<[\/]?b>$/\1/i;
  228.        # as said let's first check if the keyword is part of a multiword item
  229.        # fast seach for firstword existance:
  230.        if ($keyLength = $firstWord{$tmpWord}) {
  231.           if (&checkManyWords($keyLength, $i)) {
  232. #             print "Succesful match of multi words\n";
  233.              $i += $keyLength-1;  # skip all matched words ($i was already incremented by 1)
  234.           } 
  235.        } # if there is a chance for a multiword key.
  236.        elsif ($keyLength = &checkPairedWords($i)) { # now look of a paired keywords
  237. #             print "Succesful match of paired words\n";
  238.              $i += $keyLength-1;  # skip all matched words
  239.        } elsif ($keyLength = &checkOne($i)) {
  240. #            print "Succesful match of Single words\n";
  241.             # no need to skip all matched words
  242.        } else {
  243.             &checkPluralEtc($i);
  244.        }
  245. #        $scanKey = ($prevWords ne "") ? $prevWords . " " . $tmpWord : $tmpWord;
  246. #        if ($lexItems{$scanKey} &&  $scanKey ne $curKey) {  
  247. #           print " Word found: $scanKey, in text -- $curKey\n";
  248. #           @keyWord = split(/\s+/,$scanKey);
  249. #           if ($#keyWord > 1) {
  250. #              print " good results found it\n";
  251. #              $prevWords = "";
  252. #              $numOfWords = 0;
  253. #          } # keywords has more than 1 word
  254. #        } #found exactly as appreas in master keywords 
  255. #        elsif ($firstWord{$tmpWord} < 2) { 
  256. #              $prevWords = "";
  257. #              $numOfWords = 0;
  258. #        }
  259. #        else {
  260. #              $prevWords = $prevWords . " " . $tmpWord;
  261. #              $numOfWords++;
  262. #              print " a long prev word found --- $prevWords -- $numOfWords\n";
  263. #           
  264. #        } # 
  265.     } # for
  266. }
  267.  
  268. sub checkManyWords
  269. {
  270.     local ($numOfWords, $curIndex) = @_;
  271.     my $tmpIdx, $tmpStr;
  272.     my $i;
  273.     $tmpIdx = $curIndex + $numOfWords; 
  274.     $tmpStr = $splitWords[$curIndex];
  275.     for ($i = 1; $i < $numOfWords; $i++) {
  276.       # concatenate the next $numOfWords into one keyword
  277.       $tmpStr = $tmpStr . " " . $splitWords[$curIndex+$i];
  278.     } # for
  279.     $tmpStr =~ tr/a-z/A-Z/;
  280.     $tmpStr =~ s/\@[IB]\@([^\@]*)/\1/ig;
  281.     chop($tmpStr) if $tmpStr =~ /[\,\.\:\;\!\?\"\x93\x94\x92\x91\x27]$/;
  282.     chop($tmpStr) if $tmpStr =~ /\)$/;
  283.     if ($tmpStr =~ /^\(/) {
  284.        $tmpStr = substr ($tmpStr, 1);
  285.     }
  286.     if ($tmpStr =~ /^(.*)\'s$/i) {
  287.        $tmpStr = $1;
  288.     }
  289.     $theIndex = $lexItems{$tmpStr};
  290. #    print " Value of index $lexItems{$tmpStr}\n" if $theIndex;
  291.     if ($theIndex && (($theDir ne "Lexicon") || ($theIndex != $fileIdx))) {
  292. #       for ($i = 0; $i < $numOfWords; $i++) {
  293. #          $splitWords[$curIndex+$i] =~ s/^/\@$theIndex\@/;
  294. #          print "$splitWords[$curIndex+$i] ";
  295.    # This was the old method
  296.     #   $splitWords[$curIndex] =~ s/^/\<$theIndex\>/;
  297.     #   $splitWords[$curIndex + $numOfWords-1] =~ s/$/\<\/$theIndex\>/;
  298. #        print "Added tag in checkManyWords - $splitWords[$curIndex]\n";
  299.         for ($i = $curIndex; $i < $curIndex+$numOfWords ; $i++) {
  300.            $splitWords[$i] =~ s/^/\@\+$theIndex\@/;
  301.         }
  302. #       } # for
  303. #       print "\n";
  304.        
  305.     }
  306.     $retVal = $lexItems{$tmpStr};
  307. } # checkManyWords
  308.  
  309.  
  310. sub checkPairedWords
  311. {
  312.     local ($curIndex) = @_;
  313.     my $tmpStr, $secondPair;
  314.     
  315.     $tmpStr = $splitWords[$curIndex];
  316.     $tmpStr =~ tr/a-z/A-Z/;
  317.     $tmpStr =~ s/\@[IB]\@([^\@]*)/\1/ig;
  318.     if ($secondPair = $pairedItems{$tmpStr}) {
  319. #        print "=-=-=-= $secondPair = $splitWords[$curIndex]  =-= $tmpStr\n";
  320.         @tmpArr = split(/\s+/,$secondPair);
  321.         $arrLen = $#tmpArr ? $#tmpArr : 1;
  322.        if (&checkManyPair($arrLen+1, $curIndex)) {
  323. #             print "!!!!Succesful match of First Paired words\n";
  324.              $retVal = $arrLen+1;
  325.        } else {
  326.              $retVal = 0;
  327.        }
  328.     } else {
  329.         $retVal = 0;
  330.     }
  331. }
  332.  
  333. sub checkManyPair
  334. {
  335.     local ($numOfWords, $curIndex) = @_;
  336.     my $tmpIdx, $tmpStr;
  337.     my $i;
  338.     $tmpIdx = $curIndex + $numOfWords; 
  339.     $tmpStr = $splitWords[$curIndex];
  340.     for ($i = 1; $i < $numOfWords; $i++) {
  341.       # concatenate the next $numOfWords into one keyword
  342.       $tmpStr = $tmpStr . " " . $splitWords[$curIndex+$i];
  343.     } # for
  344. #    print " in CheckManyPair $tmpStr\n";
  345.     $tmpStr =~ tr/a-z/A-Z/;
  346.     $tmpStr =~ s/\@[IB]\@([^\@]*)/\1/ig;
  347. #    print " after CheckManyPair $tmpStr\n";
  348.     chop($tmpStr) if $tmpStr =~ /[\,\.\:\;\!\?\"\x93\x94\x92\x91\x27]$/;
  349.     chop($tmpStr) if $tmpStr =~ /\)$/;
  350.     if ($tmpStr =~ /^\(/) {
  351.        $tmpStr = substr ($tmpStr, 1);
  352.     }
  353.     if ($tmpStr =~ /^(.*)\'s$/i) {
  354.        $tmpStr = $1;
  355.     }
  356.     $theIndex = $pairLexKey{$tmpStr};
  357. #    print " after CheckManyPair the Index $theIndex,$tmpStr\n";
  358. #    print " Value of index (in pair) $pairLexKey{$tmpStr}\n" if $theIndex;
  359.     if ($theIndex && (($theDir ne "Lexicon") || ($theIndex != $fileIdx))) {
  360. #       for ($i = 0; $i < $numOfWords; $i++) {
  361. #          $splitWords[$curIndex+$i] =~ s/^/\@$theIndex\@/;
  362.    # This was the old method
  363.    #    $splitWords[$curIndex] =~ s/^/\<$theIndex\>/;
  364.    #    $splitWords[$curIndex + $numOfWords-1] =~ s/$/\<\/$theIndex\>/;
  365.         for ($i = $curIndex; $i < $curIndex+$numOfWords ; $i++) {
  366.            $splitWords[$i] =~ s/^/\@\+$theIndex\@/;
  367.         }
  368. #        print "Added tag in checkManyPairs - $splitWords[$curIndex]\n";
  369. #          print "$splitWords[$curIndex+$i] ";
  370. #       } # for
  371. #       print "\n";
  372.        
  373.     }
  374.     $retVal = $theIndex;
  375. } # checkManyPair
  376.  
  377. sub checkOne
  378. {
  379.     local ($curIndex) = @_;
  380.      my $tmpStr;
  381.     
  382.     $tmpStr = $splitWords[$curIndex];
  383.     $tmpStr =~ tr/a-z/A-Z/;
  384.     $tmpStr =~ s/\@[IB]\@([^\@]*)/\1/ig;
  385.     chop($tmpStr) if $tmpStr =~ /[\,\.\:\;\!\?\"\x93\x94\x92\x91\x27]$/;
  386.     chop($tmpStr) if $tmpStr =~ /\)$/;
  387.     if ($tmpStr =~ /^\(/) {
  388.        $tmpStr = substr ($tmpStr, 1);
  389.     }
  390.     if ($tmpStr =~ /^(.*)[\'\x92\x91\x27]S$/) {
  391.        $tmpStr = $1;
  392.     }
  393.     
  394.     $theIndex = $lexItems{$tmpStr};
  395. #    print " Value of index $lexItems{$tmpStr}\n" if $theIndex;
  396. #    if ($theIndex && $firstPaired{$fileIdx} =~ /\b$tmpStr\b/) {
  397. #       print " match first pair in file $fileIdx, entry $tmpStr - $firstPaired{$fileIdx}\n";
  398. #    }
  399.     if ($theIndex &&  (($theDir ne "Lexicon") || ($theIndex != $fileIdx)) && ($firstPaired{$fileIdx} !~ /\b$tmpStr\b/)) {
  400. #       $splitWords[$curIndex] =~ s/^/\@$theIndex\@/;
  401.    # This was the old method
  402.    #    $splitWords[$curIndex] =~ s/^(.*)$/\<$theIndex\>\1\<\/$theIndex\>/;       
  403.            $splitWords[$curIndex] =~ s/^/\@\+$theIndex\@/;
  404. #        print "Added tag in checkOne - $splitWords[$curIndex]\n";
  405. #       print "$splitWords[$curIndex]\n ";
  406.        $retVal = 1;
  407.     } else {
  408.        $retVal = 0;
  409.     }
  410. } # checkOne
  411.  
  412. sub checkPluralEtc
  413. {
  414.     local ($curIndex) = @_;
  415.      my $tmpStr;
  416.  
  417.     $tmpStr = $splitWords[$curIndex];
  418.     $tmpStr =~ tr/a-z/A-Z/;
  419.     $tmpStr =~ s/\@[IB]\@([^\@]*)/\1/ig;
  420.     chop($tmpStr) if $tmpStr =~ /[\,\.\:\;\!\?\"\x93\x94\x92\x91\x27]$/;
  421.     chop($tmpStr) if $tmpStr =~ /\)$/;
  422.     if ($tmpStr =~ /^\(/) {
  423.        $tmpStr = substr ($tmpStr, 1);
  424.     }
  425.     if ($tmpStr =~ /^(.*)\'S$/) {
  426.        $tmpStr = $1;
  427.     } elsif ($tmpStr =~ /^(.*)IES$/) {
  428.        $tmpStr = $1 . "Y";
  429.     } elsif ($tmpStr =~ /^(.*)ES$/) {
  430.        $tmpStr = $1;
  431.     } elsif ($tmpStr =~ /^(.*)SS$/) {
  432.        return 0;
  433.     } elsif ($tmpStr =~ /S$/) {   # regular plural
  434.        chop($tmpStr);
  435.     } else {
  436.        return 0;
  437.     }
  438.        
  439.     
  440.     $theIndex = $lexItems{$tmpStr};
  441. #    print " Value of index(Plural) $lexItems{$tmpStr}\n" if $theIndex;
  442.     if ($theIndex && (($theDir ne "Lexicon") || ($theIndex != $fileIdx))  && ($firstPaired{$fileIdx} !~ /\b$tmpStr\b/)) {
  443.    # This was the old method
  444.     #   $splitWords[$curIndex] =~ s/^(.*)$/\<$theIndex\>\1\<\/$theIndex\>/;
  445.            $splitWords[$curIndex] =~ s/^/\@\+$theIndex\@/;
  446. #        print "Added tag in checkPlural Etc. - $splitWords[$curIndex]\n";
  447. #       $splitWords[$curIndex] =~ s/^/\@$theIndex\@/;
  448. #       print "(Plural) $splitWords[$curIndex]\n ";
  449.        $retVal = 1;
  450.     } else {
  451.        $retVal = 0;
  452.     }
  453. } # checkPluralEtc
  454.  
  455. sub printKeyArr
  456. {
  457.    local($arRef) = @_;
  458.    foreach $key (keys (%$arRef)) {
  459.       print " The Key $key and its val $$arRef{$key}\n";
  460.    }
  461. }   
  462.